using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 定义属性类型的枚举
public enum StatType
{
    strength,       // 力量
    agility,        // 敏捷
    intelegence,    // 智力
    vitality,       // 生命力
    damage,         // 伤害
    critChance,     // 暴击几率
    critPower,      // 暴击威力
    health,         // 生命值
    armor,          // 护甲
    evasion,        // 闪避
    magicRes,       // 魔法抗性
    fireDamage,     // 火焰伤害
    iceDamage,      // 冰霜伤害
    lightingDamage  // 闪电伤害
}

public class CharacterStats : MonoBehaviour
{
    private EntityFX fx;//fx脚本
    [Header("能力-Major stats")]
    public Stat strength;//力量
    public Stat agility;//敏捷
    public Stat intelligence;//智力
    public Stat vitality;//活力

    [Header("防御-Defensive stats")]
    public Stat maxHealth;//最大hp
    public Stat armor;//护甲
    public Stat evasion;//闪避
    public Stat magicResistance;//魔法抵抗

    [Header("元素伤害-Magic stats")]
    public Stat fireDamage;//火焰
    public Stat iceDamage;//寒冰
    public Stat lightingDamage;//雷电

    [Header("暴击-Offensive stats")]
    public Stat critChance;//暴击概率
    public Stat critPower;//暴击倍率
    [Space]
    public bool isIgnited;//点燃状态，持续受到伤害
    public bool isChilled;//寒冷状态。减速减少护甲
    public bool isShocked;//减少命中几率

    [SerializeField] private float ailmentsDuration = 4;

    private float igniteTimer;//点燃时间
    private float igniteDamageCooldown = .3f;//点燃伤害间隔
    private float igniteDamageTimer;//点燃持续伤害计时
    private int igniteDamage;//点燃伤害

    private float chilledTimer;//寒冷时间

    private float shockTimer;//雷电时间
    private int shockDamage;//雷电伤害
    [SerializeField] private GameObject shockStrikePrefab;//雷电预制体


    [Tooltip("当前Hp")]
    public int currentHealth;//当前hp
    public Stat damage;//伤害值

    public System.Action onHealthChanged;//hp改变事件

    public bool isDead { get; private set; }//死亡判定
    public bool isInvincible { get; private set; }//无敌判定
    public bool isVulnerable;// 脆弱状态



    protected virtual void Start()
    {
        critPower.SetDefaultValue(150);//设置暴击倍数1.5
        currentHealth = GetMaxHealthValue();//获取最大生命值
        fx = GetComponent<EntityFX>();//获取fx脚本
    }


    protected virtual void Update()
    {
        igniteTimer -= Time.deltaTime;//火焰持续定时器
        chilledTimer -= Time.deltaTime;//寒冰持续定时器
        shockTimer -= Time.deltaTime;//雷电持续定时器
        igniteDamageTimer -= Time.deltaTime;//点燃定时器

        if (igniteTimer <= 0)
        {
            isIgnited = false;
        }
        if (chilledTimer <= 0)
        {
            isChilled = false;
        }
        if (shockTimer <= 0)
        {
            isShocked = false;
        }
        // 灼烧点燃
        if (isIgnited)
            ApplyIgniteDamage();
    }

    // 使对象在指定时间内处于脆弱状态
    public void MakeVulnerableFor(float _duration)
    {
        StartCoroutine(VulnerableForCorutine(_duration)); // 启动协程
    }

    // 协程：在指定时间内使对象处于脆弱状态
    private IEnumerator VulnerableForCorutine(float _duration)
    {
        isVulnerable = true; // 设置对象为脆弱状态
        yield return new WaitForSeconds(_duration); // 等待指定时间
        isVulnerable = false; // 恢复对象为非脆弱状态
    }

    // 增加属性的方法 数值、时间、属性
    public virtual void IncreaseStatBy(int _modifier, float _duration, Stat _GetStat)
    {
        // 启动协程来修改属性
        StartCoroutine(StatModCoroutine(_modifier, _duration, _GetStat));
    }

    // 修改属性的协程
    private IEnumerator StatModCoroutine(int _modifier, float _duration, Stat _GetStat)
    {
        // 增加属性修饰符
        _GetStat.AddModifier(_modifier);
        // 等待指定的持续时间
        yield return new WaitForSeconds(_duration);
        // 移除属性修饰符
        _GetStat.RemoveModifier(_modifier);
    }

    // 造成伤害
    public virtual void DoDamage(CharacterStats _targetStats)
    {
        // 判断是否闪避
        if (TargetCanAvoidAttack(_targetStats))
        {
            return;
        }
        bool criticalStrike = false;

        _targetStats.GetComponent<Entity>().SetupKnockbackDir(transform);
        //计算攻击加力量造成的伤害
        int totalDamage = damage.GetValue() + strength.GetValue();
        //暴击后计算暴击伤害
        if (CanCrit())
        {
            totalDamage = CalculateCriticalDamge(totalDamage);
            criticalStrike = true;
        }
        //攻击特效
        fx.CreatHitFx(_targetStats.transform, criticalStrike);
        //减去护甲
        totalDamage = CheckTargetArmor(_targetStats, totalDamage);
        // 造成伤害
        _targetStats.TakeDamage(totalDamage);
        //造成魔法伤害
        // DoMagicalDamge(_targetStats);
    }

    // 受到伤害
    public virtual void TakeDamage(int _damage)
    {
        if (isInvincible) return;//无敌不受到伤害
        DecreaseHealthBy(_damage);//被造成_damage点伤害
        GetComponent<Entity>().DamageImpact();//击退
        fx.StartCoroutine("FlashFx");//受击动画

        if (currentHealth <= 0 && !isDead)//HP小于0死亡
        {
            Die();//调用死亡的方法
        }
    }
    // 受到伤害计算
    protected virtual void DecreaseHealthBy(int _damage)
    {
        if (isVulnerable)
            _damage = Mathf.RoundToInt(_damage * 1.1f);
        currentHealth -= _damage;
        if (_damage > 0)
        {
            fx.CreatePopUpText(_damage.ToString());
        }
        if (onHealthChanged != null)// hp改变事件被订阅
        {
            onHealthChanged();
        }
    }

    // 死亡
    protected virtual void Die()
    {
        isDead = true;
    }

    // 死亡区域调用
    public void KillEntity()
    {
        if (!isDead)
            Die();
    }

    // 
    public void MakeInvincible(bool _invincible) => isInvincible = _invincible;

    // 治疗增加血量
    public virtual void IncreaseHealthBy(int _amount)
    {
        currentHealth += _amount;
        if (currentHealth > GetMaxHealthValue())
        {
            currentHealth = GetMaxHealthValue();
        }
        // 可以省略上面的用下面这句限制最大血量
        // currentHealth = Mathf.Clamp(currentHealth + _amount, 0, maxHealth.GetValue());
        if (onHealthChanged != null)
        {
            onHealthChanged();
        }
    }

    #region 魔法伤害
    // 造成魔法伤害
    public virtual void DoMagicalDamge(CharacterStats _targetStats)
    {
        // 获取魔法伤害数值
        int _fireDamage = fireDamage.GetValue();
        int _iceDamage = iceDamage.GetValue();
        int _lightingDamage = lightingDamage.GetValue();
        //全部加起来为总伤害,智力也加伤害
        int totalMagicalDamage = _fireDamage + _iceDamage + _lightingDamage + intelligence.GetValue();
        // 根据法抗计算伤害
        totalMagicalDamage = CheckTargetResistance(_targetStats, totalMagicalDamage);
        // 造成魔法伤害
        _targetStats.TakeDamage(totalMagicalDamage);

        if (Mathf.Max(_fireDamage, _iceDamage, _lightingDamage) <= 0)
        {
            return;
        }
        // 确定敌人收到的是什么类型的魔法伤害
        AttemptyToApplyAilements(_targetStats, _fireDamage, _iceDamage, _lightingDamage);

    }

    // 确定敌人收到的是什么类型的魔法伤害
    private void AttemptyToApplyAilements(CharacterStats _targetStats, int _fireDamage, int _iceDamage, int _lightingDamage)
    {
        // 确定敌人收到的是什么类型的魔法伤害
        bool canApplyIgnite = _fireDamage > _iceDamage && _fireDamage > _lightingDamage;
        bool canApplyChill = _iceDamage > _fireDamage && _iceDamage > _lightingDamage;
        bool canApplyShock = _lightingDamage > _fireDamage && _lightingDamage > _iceDamage;
        // 伤害相同随机一个元素
        while (!canApplyIgnite && canApplyChill && canApplyShock)
        {
            if (Random.value < .5f && _fireDamage > 0)
            {
                canApplyIgnite = true;
                _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
                return;
            }
            if (Random.value < .5f && _iceDamage > 0)
            {
                canApplyChill = true;
                _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
                return;
            }
            if (Random.value < .5f && _lightingDamage > 0)
            {
                canApplyShock = true;
                _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
                return;
            }
        }

        // 附带点燃伤害
        if (canApplyIgnite)
        {
            // 设置点燃伤害数值
            _targetStats.SetupIgniteDamage(Mathf.RoundToInt(_fireDamage * .2f));
        }
        // 附带雷电伤害
        if (canApplyShock)
        {
            // 设置雷电伤害数值
            _targetStats.SetupShockStrikeDamage(Mathf.RoundToInt(_lightingDamage * .1f));
        }

        //改变敌人魔法附着状态
        _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
    }

    // 受到的魔法状态
    public void ApplyAilments(bool _ignite, bool _chill, bool _shock)
    {
        bool canApplyIgnite = !isIgnited && !isChilled && !isShocked;
        bool canApplyChill = !isIgnited && !isChilled && !isShocked;
        bool canApplyShock = !isIgnited && !isChilled;

        if (_ignite && canApplyIgnite)
        {
            isIgnited = _ignite;//火焰状态
            igniteTimer = ailmentsDuration;//火焰时间
            fx.igniteFxFor(ailmentsDuration);//火焰状态表现，以下相同
        }
        if (_chill && canApplyChill)
        {
            isChilled = _chill;
            chilledTimer = ailmentsDuration;

            float slowPercentage = .2f;
            GetComponent<Entity>().SlowEntityBy(slowPercentage, ailmentsDuration);//实际会调用player或enemy中的
            fx.ChillFxFor(ailmentsDuration);
        }
        if (_shock && canApplyShock)
        {
            if (!isShocked)
            {
                ApplyShock(_shock);
            }
            else
            {
                if (GetComponent<Player>() != null) return;
                // 雷电状态弹射雷电
                HitNearestTargetWithShockStrike();
            }
        }
    }

    // 灼烧点燃
    private void ApplyIgniteDamage()
    {
        if (igniteDamageTimer < 0)//点燃冷却结束且火焰状态
        {
            DecreaseHealthBy(igniteDamage);//造成点燃伤害
            igniteDamageTimer = igniteDamageCooldown;//重置点燃间隔
            if (currentHealth <= 0 && !isDead)//死亡
            {
                // isIgnited = false;//防止死亡还在点燃，有isDead就不需要了
                Die();
            }
        }
    }

    // 赋予雷电状态
    public void ApplyShock(bool _shock)
    {
        if (isShocked) return;
        isShocked = _shock;
        shockTimer = ailmentsDuration;
        fx.ShockFxFor(ailmentsDuration);
    }

    // 雷电状态弹射雷电
    private void HitNearestTargetWithShockStrike()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 25);// 范围内搜索敌人
        float closestDistance = Mathf.Infinity;// 正无穷
        Transform closestEnemy = null;
        foreach (var hit in colliders)// 循环范围内碰撞体
        {
            // 判断敌人范围内敌人
            if (hit.GetComponent<Enemy>() != null && Vector2.Distance(transform.position, hit.transform.position) > 1)
            {
                float distanceToEnemy = Vector2.Distance(transform.position, hit.transform.position);// 获取敌人距离
                if (distanceToEnemy < closestDistance)// 筛选出最短距离的敌人
                {
                    closestDistance = distanceToEnemy;
                    closestEnemy = hit.transform;
                }
            }

        }
        if (closestEnemy == null) closestEnemy = transform;
        if (closestEnemy != null)
        {
            GameObject newShockStrike = Instantiate(shockStrikePrefab, transform.position, Quaternion.identity);
            newShockStrike.GetComponent<ShockStrike_Controller>().Setup(shockDamage, closestEnemy.GetComponent<CharacterStats>());
        }
    }

    // 设置灼烧伤害
    public void SetupIgniteDamage(int _damage)
    {
        igniteDamage = _damage;
    }
    // 设置雷电伤害
    public void SetupShockStrikeDamage(int _damage)
    {
        shockDamage = _damage;
    }

    // 魔法抵抗减伤计算
    private int CheckTargetResistance(CharacterStats _targetStats, int totalMagicalDamage)
    {
        totalMagicalDamage -= _targetStats.magicResistance.GetValue() + (_targetStats.intelligence.GetValue() * 3);
        totalMagicalDamage = Mathf.Clamp(totalMagicalDamage, 0, int.MaxValue);
        return totalMagicalDamage;
    }

    #endregion

    #region 计算区域
    // 护甲减伤计算
    protected int CheckTargetArmor(CharacterStats _targetStats, int totalDamage)
    {
        if (_targetStats.isChilled)
        {
            //敌人寒冷状态减少护甲
            totalDamage -= Mathf.RoundToInt(_targetStats.armor.GetValue() * 0.8f);
        }
        else
        {
            //减去护甲
            totalDamage -= _targetStats.armor.GetValue();
        }
        // 限制伤害大于0
        totalDamage = Mathf.Clamp(totalDamage, 0, int.MaxValue);
        return totalDamage;
    }

    // 躲避
    public virtual void OnEvasion()
    {

    }

    // 目标闪避
    protected bool TargetCanAvoidAttack(CharacterStats _targetStats)
    {
        // 计算闪避几率
        int totalEvasion = _targetStats.evasion.GetValue() + _targetStats.agility.GetValue();
        if (isShocked)
        {
            // 自身雷电状态增加对方闪避率
            totalEvasion += 20;
        }
        if (Random.Range(0, 100) < totalEvasion)
        {
            _targetStats.OnEvasion();
            return true;
        }
        return false;
    }

    // 暴击率计算
    protected bool CanCrit()
    {
        //敏捷度提高暴击率
        int totalCriticalChance = critChance.GetValue() + agility.GetValue();
        if (Random.Range(0, 100) < totalCriticalChance)
        {
            return true;
        }
        return false;
    }

    // 计算暴击伤害
    protected int CalculateCriticalDamge(int _damage)
    {
        float totalCritPower = (critPower.GetValue() + strength.GetValue()) * .01f;
        float critDamge = _damage * totalCritPower;
        return Mathf.RoundToInt(critDamge);
    }

    // 获取最大HP
    public int GetMaxHealthValue()
    {
        return maxHealth.GetValue() + vitality.GetValue() * 5;
    }

    #endregion

    // 根据_statType返回对应的属性
    public Stat GetStat(StatType _statType)
    {
        switch (_statType)
        {
            case StatType.strength:
                return strength;
            case StatType.agility:
                return agility;
            case StatType.intelegence:
                return intelligence;
            case StatType.vitality:
                return vitality;
            case StatType.damage:
                return damage;
            case StatType.critChance:
                return critChance;
            case StatType.critPower:
                return critPower;
            case StatType.health:
                return maxHealth;
            case StatType.armor:
                return armor;
            case StatType.evasion:
                return evasion;
            case StatType.magicRes:
                return magicResistance;
            case StatType.fireDamage:
                return fireDamage;
            case StatType.iceDamage:
                return iceDamage;
            case StatType.lightingDamage:
                return lightingDamage;
            default:
                return null;
        }
    }



}
